package cn.tedu.apiday08;

//售票窗口案例方式2 实现Runnable接口
//目前程序中有安全隐患， 加锁来解决， 锁的位置   锁的对象（同一个）
public class TextText1 {
    public static void main(String[] args) {
        MyTickets1 my = new MyTickets1();
//        MyTickets1 my1 = new MyTickets1();
//        MyTickets1 my2 = new MyTickets1();
//        MyTickets1 my3 = new MyTickets1();
        Thread t = new Thread(my);
        Thread t1 = new Thread(my);
        Thread t2 = new Thread(my);
        Thread t3 = new Thread(my);
        t.setName("1号窗口");
        t1.setName("2号窗口");
        t2.setName("3号窗口");
        t3.setName("4号窗口");
        t.start();
        t1.start();
        t2.start();
        t3.start();


    }
}
class  MyTickets1 implements  Runnable {
    int tickets = 10;//static可以不修饰，原因是因为只有一个my对象，

    Object object = new Object();
    @Override
    public void run() {
        while (true) {//一直卖票
            //t t1 t2 t3 四个进行判断  假设只剩下了一张票  但是四个人都满足了条件
            //锁位置  从问题起点开始   同步代码块 需要同时指定锁对象，可以是任意对象，但是必须是同一个对象
            //synchronized (new Object()){//new Object()四个线程来了 使用的每次都是new出来的对象，没有统一，不是同一个对象
            synchronized (object) {//四个线程来了，使用的都是new出来的Object同一个对象
                //synchronized (this)四个线程来了，使用的都是本类的对象this
                if (tickets > 0) {
                    //问题2  超卖  程序卖出了 -1  0 -2
                    //原因：
                    //问题3 重卖 程序把一张票卖给多人
                    //原因 ： 假设t休息好了，现在tickets = 73，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出1  在变成0，还没有来得及变
                    //t刚弄好，假设t1休息好了，现在tickets=73，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出73  在变成72，还没有来得及变
                    //t1刚弄好，假设t2休息好了，现在tickets=73，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出73  在变成72
                    //t2刚弄好，假设t3休息好了，现在tickets=72，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出72  在变成71
                    //让程序休息一下，如果数据仍然是正确的   那么这个多线程程序才是完美的
                    try {
                        //t t1 t2 t3 四个都休息了10毫秒
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //超卖原因 ： 假设t休息好了，现在tickets = 1，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出1  在变成0
                    //t刚弄好，假设t1休息好了，现在tickets=0，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出0  在变成-1
                    //t1刚弄好，假设t2休息好了，现在tickets=-1，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出-1  在变成-2
                    //t2刚弄好，假设t3休息好了，现在tickets=-2，开始执行tickets--，执行tickets--  因为是减减在后，所以先输出-2  在变成-3
                    System.out.println(Thread.currentThread().getName() + "===========" + tickets--);//获取线程名称
                } else {
                    break;
                }
            }
        }
    }
}